<template>
  <div
    class="content-box"
    :class="{ padding: customLoading }"
    @touchstart="touchEventStart"
    @touchmove="touchEventMove"
    @touchend="touchEventEnd"
    :style="{ top: currentTop + 'px' }"
  >
    <van-pull-refresh
      success-text="刷新成功"
      v-model="isLoading"
      @refresh="onRefresh"
      :disabled="!dropdownRefresh"
    >
      <van-list
        class="list-box"
        v-model="loading"
        :finished="finished"
        :error.sync="haveError"
        @load="onLoad"
        :style="{ 'background-color': bgColor }"
      >
        <default-page
          v-if="dataSource.length == 0 && showDefaultPage"
        ></default-page>
        <div
          v-for="(item, index) in dataSource"
          :key="index"
          @click="parentClick(item)"
          v-else
        >
          <slot :data="item" :dataIndex="index"></slot>
        </div>

        <template #loading>
          <van-loading size="24px" color="#E60033"></van-loading>
        </template>
        <template #finished v-if="dataSource.length != 0 && !customLoading">
          <span v-if="hasMore"></span>
          <span v-else-if="haveError"></span>
          <span v-else class="finished-text">{{ finishedText }}</span>
        </template>
        <template #error>
          <span @click="onErrorRefresh">请求失败，点击重新加载</span>
        </template>
      </van-list>
    </van-pull-refresh>
    <!-- 自定义上拉刷新 -->
    <div class="load-box" v-if="customLoading">
      <van-loading size="24px" class="loading" color="#f00">
        刷新中...
      </van-loading>
    </div>
  </div>
</template>

<script>
import defaultPage from "@/components/template/DefaultPage.vue";
import Qs from "qs";
export default {
  name: "listSingle",
  props: {
    apiUrl: {
      //列表数据的请求接口API地址
      type: String,
      required: true
    },
    apiParams: {
      //列表数据的请求接口的参数对象，默认为current=1&size=10
      type: Object,
      default: () => {}
    },
    dropdownRefresh: {
      //是否支持下拉刷新 默认不支持
      type: Boolean,
      default: false
    },
    bgColor: {
      type: String,
      default: "#fff"
    },
    finishedText: {
      type: String,
      default: "更多精彩，敬请期待"
    },
    showDefaultPage: {
      type: Boolean,
      default: true
    },
    // 设置旧数据为已结束
    module: {
      type: String,
      default: ""
    },
    noPage: {
      type: Boolean,
      default: false
    }
  },
  watch: {
    apiParams: {
      handler(params) {
        this.onLoad(params);
      },
      deep: true
    }
  },
  data() {
    return {
      dataSource: [], //列表的数据源
      // 分页
      pagination: {
        current: 1,
        pageSize: 10,
        total: 0
      },
      loading: false,
      finished: false,
      haveError: false,
      isLoading: false, //下拉刷新是否加载完成
      hasMore: false,
      currentTop: 0,
      customLoading: false,
      canReflesh: false
    };
  },
  components: { defaultPage },
  created() {
    window.addEventListener("scroll", this.listenSroll);
  },
  methods: {
    parentClick(item) {
      this.$emit("itemClick", item);
    },
    //下拉刷新
    onRefresh() {
      this.pagination.current = 1;
      this.dataSource = [];
      this.onLoad();
    },
    //这里是list 的请求事件
    onLoad(p = null) {
      if (!this.apiUrl) {
        // eslint-disable-next-line
        // console.log("单列列表的请求地址不能为空！！！");
        this.loading = false;
        this.finished = true;
        return;
      }
      let params = {};
      if (!this.apiParams && !p) {
        params.page = this.pagination.current;
        params.pageSize = this.pagination.pageSize;
      } else if (p) {
        params = Object.assign({ page: 1, pageSize: 10 }, p);
        // 重置列表数据
        this.dataSource = [];
        // 重置分页器状态
        this.pagination.current;
      } else {
        params = Object.assign(params, this.apiParams);
        params.page = this.pagination.current;
        params.pageSize = this.pagination.pageSize;
      }
      let that = this;
      const d = Qs.stringify({
        ...this.apiParams,
        limit: params.pageSize,
        offset: (params.page - 1) * params.pageSize
      });
      this.$axios
        .post(this.apiUrl + `?${d}`)
        .then(res => {
          if (this.isLoading) {
            this.dataSource = [];
            this.isLoading = false;
          }
          let resData;
          resData = res.rows || [];
          this.transData(res, resData, params);
        })
        .catch(error => {
          that.finished = true;
          // eslint-disable-next-line
          // console.log(error);
          that.haveError = true;
        })

        .finally(() => {
          // always executed
          this.loading = false;
          // this.isLoading = false;
          // this.finished = true;
        });
    },
    // 处理返回的数据
    transData(res, resData, params) {
      if (params.page == 1 || params.pageIndex == 1) {
        this.dataSource = resData;
      } else {
        this.dataSource = this.dataSource.concat(resData);
      }
      this.pagination.total = Number(res.total) || resData.length;
      // this.$emit("showLen", res.data.totalCount);
      if (resData.length < params.pageSize || this.noPage) {
        this.finished = true;
        this.haveError = false;
      } else {
        this.pagination.current++;
      }
    },
    //错误文本的点击事件
    onErrorRefresh() {
      this.haveError = false;
      this.finished = false;
      this.loading = true;
      this.onLoad();
    },
    touchEventStart(e) {
      if (!this.canReflesh) return; // 列表未加载完毕不触发效果
      this.start = e.changedTouches[0].clientY;
    },
    touchEventMove(e) {
      if (!this.canReflesh) return; // 列表未加载完毕不触发效果
      const current = (this.start - e.changedTouches[0].clientY) / 2;
      if (current < 50) {
        this.currentTop = -current;
      }
    },
    touchEventEnd(e) {
      if (!this.canReflesh) return; // 列表未加载完毕不触发效果
      const current = this.start - e.changedTouches[0].clientY;
      // 起始值大于结束值设定值进行刷新
      if (current > 20) {
        this.customLoading = true;
        setTimeout(() => {
          this.customLoading = false;
        }, 2000);
      }
      this.currentTop = 0;
    },
    listenSroll() {
      const scrollTop =
        document.documentElement.scrollTop || document.body.scrollTop;
      const windowHeight =
        document.documentElement.clientHeight || document.body.clientHeight;
      const scrollHeight =
        document.documentElement.scrollHeight || document.body.scrollHeight;
      if (scrollTop + windowHeight == scrollHeight) {
        this.canReflesh = true;
      }
    }
  }
};
</script>

<style scoped lang="scss">
.content-box {
  width: 100%;
  height: 100%;
  position: relative;
  &.padding {
    transition: top ease-in-out 0.3s;
  }
  .list-box {
    background: #fff;
    overflow: hidden;
  }
}
.load-box {
  padding: 20px 0;
  display: flex;
  justify-content: center;
}
.finished-text {
  font-size: 24px;
  line-height: 36px;
  font-weight: 500;
  color: #cccccc;
}
</style>
